/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.lang.invoke;

import java.io.Serializable;
import java.util.Arrays;

/**
 * <p>用于促进创建简单"函数对象"的方法，这些对象
 * 通过委托给提供的{@link MethodHandle}来实现一个或多个接口，
 * 可能在类型适配和参数的部分求值之后。这些
 * 方法通常用作{@code invokedynamic}
 * 调用站点的<em>引导方法</em>，以支持Java编程语言的
 * <em>lambda表达式</em>和<em>方法引用表达式</em>特性。
 *
 * <p>对提供的{@code MethodHandle}指定行为的间接访问
 * 按顺序通过三个阶段进行：
 * <ul>
 *     <li><em>链接</em>发生在调用此类中的方法时。
 *     它们以要实现的接口（通常是
 *     <em>函数式接口</em>，具有单个抽象方法的接口）、
 *     该接口中要实现的方法的名称和签名、
 *     描述该方法所需实现行为的方法句柄
 *     以及可能的其他附加元数据作为参数，并产生一个
 *     {@link CallSite}，其目标可用于创建合适的函数
 *     对象。链接可能涉及动态加载实现目标接口的新类。
 *     {@code CallSite}可以被视为函数对象的"工厂"，
 *     因此这些链接方法被称为"元工厂"。</li>
 *
 *     <li><em>捕获</em>发生在调用{@code CallSite}的目标时，
 *     通常通过{@code invokedynamic}调用站点，
 *     产生一个函数对象。对于单个工厂{@code CallSite}，
 *     这可能发生多次。捕获可能涉及分配新的
 *     函数对象，或者可能返回现有的函数对象。
 *     行为{@code MethodHandle}可能具有超出指定接口方法的
 *     附加参数；这些被称为<em>捕获的
 *     参数</em>，必须作为参数提供给
 *     {@code CallSite}目标，并且可能早期绑定到行为
 *     {@code MethodHandle}。捕获参数的数量和类型
 *     在链接期间确定。</li>
 *
 *     <li><em>调用</em>发生在对函数对象调用已实现的接口方法时。
 *     对于单个函数对象，这可能发生多次。
 *     行为{@code MethodHandle}引用的方法
 *     使用捕获的参数和调用时提供的任何附加参数调用，
 *     就像通过{@link MethodHandle#invoke(Object...)}一样。</li>
 * </ul>
 *
 * <p>It is sometimes useful to restrict the set of inputs or results permitted
 * at invocation.  For example, when the generic interface {@code Predicate<T>}
 * is parameterized as {@code Predicate<String>}, the input must be a
 * {@code String}, even though the method to implement allows any {@code Object}.
 * At linkage time, an additional {@link MethodType} parameter describes the
 * "instantiated" method type; on invocation, the arguments and eventual result
 * are checked against this {@code MethodType}.
 *
 * <p>This class provides two forms of linkage methods: a standard version
 * ({@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)})
 * using an optimized protocol, and an alternate version
 * {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}).
 * The alternate version is a generalization of the standard version, providing
 * additional control over the behavior of the generated function objects via
 * flags and additional arguments.  The alternate version adds the ability to
 * manage the following attributes of function objects:
 *
 * <ul>
 *     <li><em>Bridging.</em>  It is sometimes useful to implement multiple
 *     variations of the method signature, involving argument or return type
 *     adaptation.  This occurs when multiple distinct VM signatures for a method
 *     are logically considered to be the same method by the language.  The
 *     flag {@code FLAG_BRIDGES} indicates that a list of additional
 *     {@code MethodType}s will be provided, each of which will be implemented
 *     by the resulting function object.  These methods will share the same
 *     name and instantiated type.</li>
 *
 *     <li><em>Multiple interfaces.</em>  If needed, more than one interface
 *     can be implemented by the function object.  (These additional interfaces
 *     are typically marker interfaces with no methods.)  The flag {@code FLAG_MARKERS}
 *     indicates that a list of additional interfaces will be provided, each of
 *     which should be implemented by the resulting function object.</li>
 *
 *     <li><em>Serializability.</em>  The generated function objects do not
 *     generally support serialization.  If desired, {@code FLAG_SERIALIZABLE}
 *     can be used to indicate that the function objects should be serializable.
 *     Serializable function objects will use, as their serialized form,
 *     instances of the class {@code SerializedLambda}, which requires additional
 *     assistance from the capturing class (the class described by the
 *     {@link MethodHandles.Lookup} parameter {@code caller}); see
 *     {@link SerializedLambda} for details.</li>
 * </ul>
 *
 * <p>Assume the linkage arguments are as follows:
 * <ul>
 *      <li>{@code invokedType} (describing the {@code CallSite} signature) has
 *      K parameters of types (D1..Dk) and return type Rd;</li>
 *      <li>{@code samMethodType} (describing the implemented method type) has N
 *      parameters, of types (U1..Un) and return type Ru;</li>
 *      <li>{@code implMethod} (the {@code MethodHandle} providing the
 *      implementation has M parameters, of types (A1..Am) and return type Ra
 *      (if the method describes an instance method, the method type of this
 *      method handle already includes an extra first argument corresponding to
 *      the receiver);</li>
 *      <li>{@code instantiatedMethodType} (allowing restrictions on invocation)
 *      has N parameters, of types (T1..Tn) and return type Rt.</li>
 * </ul>
 *
 * <p>Then the following linkage invariants must hold:
 * <ul>
 *     <li>Rd is an interface</li>
 *     <li>{@code implMethod} is a <em>direct method handle</em></li>
 *     <li>{@code samMethodType} and {@code instantiatedMethodType} have the same
 *     arity N, and for i=1..N, Ti and Ui are the same type, or Ti and Ui are
 *     both reference types and Ti is a subtype of Ui</li>
 *     <li>Either Rt and Ru are the same type, or both are reference types and
 *     Rt is a subtype of Ru</li>
 *     <li>K + N = M</li>
 *     <li>For i=1..K, Di = Ai</li>
 *     <li>For i=1..N, Ti is adaptable to Aj, where j=i+k</li>
 *     <li>The return type Rt is void, or the return type Ra is not void and is
 *     adaptable to Rt</li>
 * </ul>
 *
 * <p>Further, at capture time, if {@code implMethod} corresponds to an instance
 * method, and there are any capture arguments ({@code K > 0}), then the first
 * capture argument (corresponding to the receiver) must be non-null.
 *
 * <p>A type Q is considered adaptable to S as follows:
 * <table summary="adaptable types">
 *     <tr><th>Q</th><th>S</th><th>Link-time checks</th><th>Invocation-time checks</th></tr>
 *     <tr>
 *         <td>Primitive</td><td>Primitive</td>
 *         <td>Q can be converted to S via a primitive widening conversion</td>
 *         <td>None</td>
 *     </tr>
 *     <tr>
 *         <td>Primitive</td><td>Reference</td>
 *         <td>S is a supertype of the Wrapper(Q)</td>
 *         <td>Cast from Wrapper(Q) to S</td>
 *     </tr>
 *     <tr>
 *         <td>Reference</td><td>Primitive</td>
 *         <td>for parameter types: Q is a primitive wrapper and Primitive(Q)
 *         can be widened to S
 *         <br>for return types: If Q is a primitive wrapper, check that
 *         Primitive(Q) can be widened to S</td>
 *         <td>If Q is not a primitive wrapper, cast Q to the base Wrapper(S);
 *         for example Number for numeric types</td>
 *     </tr>
 *     <tr>
 *         <td>Reference</td><td>Reference</td>
 *         <td>for parameter types: S is a supertype of Q
 *         <br>for return types: none</td>
 *         <td>Cast from Q to S</td>
 *     </tr>
 * </table>
 *
 * @apiNote These linkage methods are designed to support the evaluation
 * of <em>lambda expressions</em> and <em>method references</em> in the Java
 * Language.  For every lambda expressions or method reference in the source code,
 * there is a target type which is a functional interface.  Evaluating a lambda
 * expression produces an object of its target type. The recommended mechanism
 * for evaluating lambda expressions is to desugar the lambda body to a method,
 * invoke an invokedynamic call site whose static argument list describes the
 * sole method of the functional interface and the desugared implementation
 * method, and returns an object (the lambda object) that implements the target
 * type. (For method references, the implementation method is simply the
 * referenced method; no desugaring is needed.)
 *
 * <p>The argument list of the implementation method and the argument list of
 * the interface method(s) may differ in several ways.  The implementation
 * methods may have additional arguments to accommodate arguments captured by
 * the lambda expression; there may also be differences resulting from permitted
 * adaptations of arguments, such as casting, boxing, unboxing, and primitive
 * widening. (Varargs adaptations are not handled by the metafactories; these are
 * expected to be handled by the caller.)
 *
 * <p>Invokedynamic call sites have two argument lists: a static argument list
 * and a dynamic argument list.  The static argument list is stored in the
 * constant pool; the dynamic argument is pushed on the operand stack at capture
 * time.  The bootstrap method has access to the entire static argument list
 * (which in this case, includes information describing the implementation method,
 * the target interface, and the target interface method(s)), as well as a
 * method signature describing the number and static types (but not the values)
 * of the dynamic arguments and the static return type of the invokedynamic site.
 *
 * @implNote The implementation method is described with a method handle. In
 * theory, any method handle could be used. Currently supported are direct method
 * handles representing invocation of virtual, interface, constructor and static
 * methods.
 */
public class LambdaMetafactory {

    /** 用于备用元工厂的标志，指示lambda对象
     * 必须是可序列化的 */
    public static final int FLAG_SERIALIZABLE = 1 << 0;

    /**
     * 用于备用元工厂的标志，指示lambda对象实现
     * 除Serializable之外的其他标记接口
     */
    public static final int FLAG_MARKERS = 1 << 1;

    /**
     * 用于备用元工厂的标志，指示lambda对象需要
     * 附加的桥接方法
     */
    public static final int FLAG_BRIDGES = 1 << 2;

    private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
    private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];

    /**
     * 促进创建简单"函数对象"，这些对象通过委托给提供的{@link MethodHandle}
     * 来实现一个或多个接口，在适当的类型适配和参数的部分求值之后。
     * 通常用作{@code invokedynamic}调用站点的<em>引导方法</em>，
     * 以支持Java编程语言的<em>lambda表达式</em>和<em>方法引用表达式</em>特性。
     *
     * <p>这是标准的、简化的元工厂；{@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}
     * 提供了额外的灵活性。
     * {@link LambdaMetafactory 上面}提供了此方法行为的一般描述。
     *
     * <p>当调用从此方法返回的{@code CallSite}的目标时，
     * 结果函数对象是一个类的实例，该类
     * 实现由{@code invokedType}的返回类型命名的接口，
     * 声明一个具有{@code invokedName}给定名称和
     * {@code samMethodType}给定签名的方法。它也可能重写
     * {@code Object}的附加方法。
     *
     * @param caller 表示具有调用者访问权限的查找上下文。
     *               当与{@code invokedynamic}一起使用时，
     *               这由VM自动堆叠。
     * @param invokedName 要实现的方法的名称。当与
     *                    {@code invokedynamic}一起使用时，这由
     *                    {@code InvokeDynamic}结构的{@code NameAndType}
     *                    提供，并由VM自动堆叠。
     * @param invokedType {@code CallSite}的预期签名。
     *                    参数类型表示捕获变量的类型；
     *                    返回类型是要实现的接口。当与
     *                    {@code invokedynamic}一起使用时，这由
     *                    {@code InvokeDynamic}结构的{@code NameAndType}
     *                    提供，并由VM自动堆叠。
     *                    如果实现方法是实例方法且此签名有任何参数，
     *                    调用签名中的第一个参数必须
     *                    对应于接收者。
     * @param samMethodType 要由函数对象实现的方法的签名和返回类型。
     * @param implMethod 描述实现方法的直接方法句柄，
     *                   该方法应在调用时被调用（适当适配
     *                   参数类型、返回类型，并将捕获的
     *                   参数添加到调用参数前面）。
     * @param instantiatedMethodType 应在调用时动态强制执行的签名和返回类型。
     *                               这可能与{@code samMethodType}相同，
     *                               或者可能是它的特化。
     * @return 一个CallSite，其目标可用于执行捕获，生成
     *         由{@code invokedType}命名的接口的实例
     * @throws LambdaConversionException 如果违反了{@link LambdaMetafactory 上面}
     *                                   描述的任何链接不变量
     */
    public static CallSite metafactory(MethodHandles.Lookup caller,
                                       String invokedName,
                                       MethodType invokedType,
                                       MethodType samMethodType,
                                       MethodHandle implMethod,
                                       MethodType instantiatedMethodType)
            throws LambdaConversionException {
        AbstractValidatingLambdaMetafactory mf;
        mf = new InnerClassLambdaMetafactory(caller, invokedType,
                                             invokedName, samMethodType,
                                             implMethod, instantiatedMethodType,
                                             false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY);
        mf.validateMetafactoryArgs();
        return mf.buildCallSite();
    }

    /**
     * 促进创建简单"函数对象"，这些对象通过委托给提供的{@link MethodHandle}
     * 来实现一个或多个接口，在适当的类型适配和参数的部分求值之后。
     * 通常用作{@code invokedynamic}调用站点的<em>引导方法</em>，
     * 以支持Java编程语言的<em>lambda表达式</em>和<em>方法引用表达式</em>特性。
     *
     * <p>这是通用的、更灵活的元工厂；{@link #metafactory(java.lang.invoke.MethodHandles.Lookup,
     * String, MethodType, MethodType, MethodHandle, MethodType)}
     * 提供了简化版本。
     * {@link LambdaMetafactory 上面}提供了此方法行为的一般描述。
     *
     * <p>此方法的参数列表包括三个固定参数，
     * 对应于VM在{@code invokedynamic}调用中为引导方法
     * 自动堆叠的参数，以及一个包含附加参数的{@code Object[]}
     * 参数。此方法的声明参数列表是：
     *
     * <pre>{@code
     *  CallSite altMetafactory(MethodHandles.Lookup caller,
     *                          String invokedName,
     *                          MethodType invokedType,
     *                          Object... args)
     * }</pre>
     *
     * <p>但它的行为就像参数列表如下：
     *
     * <pre>{@code
     *  CallSite altMetafactory(MethodHandles.Lookup caller,
     *                          String invokedName,
     *                          MethodType invokedType,
     *                          MethodType samMethodType,
     *                          MethodHandle implMethod,
     *                          MethodType instantiatedMethodType,
     *                          int flags,
     *                          int markerInterfaceCount,  // IF flags has MARKERS set
     *                          Class... markerInterfaces, // IF flags has MARKERS set
     *                          int bridgeCount,           // IF flags has BRIDGES set
     *                          MethodType... bridges      // IF flags has BRIDGES set
     *                          )
     * }</pre>
     *
     * <p>出现在{@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)}
     * 参数列表中的参数与该方法中的规范相同。附加参数
     * 解释如下：
     * <ul>
     *     <li>{@code flags} 表示附加选项；这是所需标志的按位
     *     OR。定义的标志有{@link #FLAG_BRIDGES}、
     *     {@link #FLAG_MARKERS}和{@link #FLAG_SERIALIZABLE}。</li>
     *     <li>{@code markerInterfaceCount} 是函数对象应实现的附加接口数量，
     *     当且仅当设置了{@code FLAG_MARKERS}标志时才存在。</li>
     *     <li>{@code markerInterfaces} 是要实现的附加接口的变长列表，
     *     其长度等于{@code markerInterfaceCount}，
     *     当且仅当设置了{@code FLAG_MARKERS}标志时才存在。</li>
     *     <li>{@code bridgeCount} 是函数对象应实现的附加方法签名数量，
     *     当且仅当设置了{@code FLAG_BRIDGES}标志时才存在。</li>
     *     <li>{@code bridges} 是要实现的附加方法签名的变长列表，
     *     其长度等于{@code bridgeCount}，
     *     当且仅当设置了{@code FLAG_BRIDGES}标志时才存在。</li>
     * </ul>
     *
     * <p>{@code markerInterfaces}命名的每个类都受到与{@code Rd}（{@code invokedType}的返回类型）
     * 相同的限制，如{@link LambdaMetafactory 上面}所述。
     * {@code bridges}命名的每个{@code MethodType}都受到与{@code samMethodType}
     * 相同的限制，如{@link LambdaMetafactory 上面}所述。
     *
     * <p>当在{@code flags}中设置FLAG_SERIALIZABLE时，函数对象
     * 将实现{@code Serializable}，并将有一个{@code writeReplace}
     * 方法返回适当的{@link SerializedLambda}。
     * {@code caller}类必须有适当的{@code $deserializeLambda$}
     * 方法，如{@link SerializedLambda}中所述。
     *
     * <p>当调用从此方法返回的{@code CallSite}的目标时，
     * 生成的函数对象是具有以下属性的类的实例：
     * <ul>
     *     <li>该类实现由{@code invokedType}的返回类型命名的接口
     *     以及由{@code markerInterfaces}命名的任何接口</li>
     *     <li>该类声明具有{@code invokedName}给定名称的方法，
     *     以及由{@code samMethodType}给定的签名和由{@code bridges}
     *     给定的附加签名</li>
     *     <li>该类可以重写{@code Object}的方法，并可以
     *     实现与序列化相关的方法。</li>
     * </ul>
     *
     * @param caller 表示具有调用者可访问性特权的查找上下文。
     *               当与{@code invokedynamic}一起使用时，
     *               这由VM自动堆叠。
     * @param invokedName 要实现的方法的名称。当与{@code invokedynamic}
     *                    一起使用时，这由{@code InvokeDynamic}结构的
     *                    {@code NameAndType}提供，并由VM自动堆叠。
     * @param invokedType {@code CallSite}的预期签名。参数类型表示
     *                    捕获变量的类型；返回类型是要实现的接口。
     *                    当与{@code invokedynamic}一起使用时，这由
     *                    {@code InvokeDynamic}结构的{@code NameAndType}
     *                    提供，并由VM自动堆叠。如果实现方法是实例方法
     *                    且此签名有任何参数，调用签名中的第一个参数
     *                    必须对应于接收者。
     * @param  args       包含所需参数{@code samMethodType}、{@code implMethod}、
     *                    {@code instantiatedMethodType}、{@code flags}和任何
     *                    可选参数的{@code Object[]}数组，如上面
     *                    {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}所述
     * @return 一个CallSite，其目标可用于执行捕获，生成
     *         由{@code invokedType}命名的接口的实例
     * @throws LambdaConversionException 如果违反了{@link LambdaMetafactory 上面}
     *                                   描述的任何链接不变量
     */
    public static CallSite altMetafactory(MethodHandles.Lookup caller,
                                          String invokedName,
                                          MethodType invokedType,
                                          Object... args)
            throws LambdaConversionException {
        MethodType samMethodType = (MethodType)args[0];
        MethodHandle implMethod = (MethodHandle)args[1];
        MethodType instantiatedMethodType = (MethodType)args[2];
        int flags = (Integer) args[3];
        Class<?>[] markerInterfaces;
        MethodType[] bridges;
        int argIndex = 4;
        if ((flags & FLAG_MARKERS) != 0) {
            int markerCount = (Integer) args[argIndex++];
            markerInterfaces = new Class<?>[markerCount];
            System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount);
            argIndex += markerCount;
        }
        else
            markerInterfaces = EMPTY_CLASS_ARRAY;
        if ((flags & FLAG_BRIDGES) != 0) {
            int bridgeCount = (Integer) args[argIndex++];
            bridges = new MethodType[bridgeCount];
            System.arraycopy(args, argIndex, bridges, 0, bridgeCount);
            argIndex += bridgeCount;
        }
        else
            bridges = EMPTY_MT_ARRAY;

        boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);
        if (isSerializable) {
            boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(invokedType.returnType());
            for (Class<?> c : markerInterfaces)
                foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
            if (!foundSerializableSupertype) {
                markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1);
                markerInterfaces[markerInterfaces.length-1] = Serializable.class;
            }
        }

        AbstractValidatingLambdaMetafactory mf
                = new InnerClassLambdaMetafactory(caller, invokedType,
                                                  invokedName, samMethodType,
                                                  implMethod,
                                                  instantiatedMethodType,
                                                  isSerializable,
                                                  markerInterfaces, bridges);
        mf.validateMetafactoryArgs();
        return mf.buildCallSite();
    }
}
